1include <BOSL2/std.scad>
  2// Voronoi from https://github.com/felipesanches/OpenSCAD_Voronoi_Generator
  3use <voronoi.scad>
  4use <NotoSansMono-Bold.ttf>
  5
  6box_diameter = 86; //mm
  7box_thickness = 28; //mm
  8box_rounding = 10;//mm
  9
 10wall_thickness = 3;//mm
 11
 12register_thickness = 1; //mm
 13register_depth = 1; //mm
 14register_tolerance = 0.1;//mm
 15register_friction_bars = 6;
 16friction_bar_thickness=0.75;//mm
 17friction_bar_length=1;//mm
 18
 19hinge_length = 60; //mm
 20hinge_width = 30; //mm
 21hinge_thickness = 0.6; //mm 3 0.2mm layers
 22hinge_rounding = 15;//mm
 23
 24bottom_voronoi_seed = 100;
 25top_voronoi_seed = 1541;
 26voronoi_count = 100;
 27voronoi_thickness=1;
 28voronoi_rounding=0.5;
 29voronoi_texture_thickness = 1.5; //mm
 30voronoi_texture = false;
 31
 32text_texture_thickness = 1.5; //mm
 33text_texture = true;
 34
 35binary_texture_thickness = 1.5; //mm
 36binary_angle_pad = 0.0; // fraction
 37binary_line_pad = 0.0; // fraction
 38binary_width = 4;
 39binary_offset = 2;
 40binary_data = ["01111010"]; //["01010010", "01000001", "00110001", "00110111", "01101000", "00110100", "00110101", "01101101", "00110100", "00110000", "00101110", "00110000", "00110100", "00110000", "00111001", "01110011","01000100", "01100101", "01100011", "11100010", "10001000", "10010010", "00110010", "00111001", "11000010", "10110000", "00110000", "11100010", "10000000", "10110010", "00110010", "00111000", "00101110", "00110001", "00110001", "00111000", "11100010", "10000000", "10110011"];
 41binary_read_start_indicator_radius = 1;
 42binary_texture = true;
 43
 44textured_interior = true;
 45interior_texture = "cubes"; // See https://github.com/revarbat/BOSL2/wiki/skin.scad#function-texture for available textures
 46interior_texture_depth = 0.4; // multiplier
 47interior_texture_size = [10,10];
 48
 49resolution = 200; // must be pair
 50
 51// code
 52hinge_length_adjusted = box_diameter+hinge_length+hinge_width;
 53
 54module voronoi_polygon(border, n=30, thickness=1.7, round=1.0, edging=3.0, seed=undef) {
 55
 56    // bounding box
 57    only_x = [ for (point = border) point[0] ];
 58    only_y = [ for (point = border) point[1] ];
 59    min_x = min(only_x);
 60    min_y = min(only_y);
 61    max_x = max(only_x);
 62    max_y = max(only_y);
 63    // echo([[min_x,min_y],[max_x,max_y]]);
 64
 65    // compute sizes, centers and scaling
 66    size_x = max_x - min_x;
 67    size_y = max_y - min_y;
 68    L = max(size_x, size_y);
 69    scale_voro = [ size_x / L, size_y / L ];
 70    center_poly = [(min_x + max_x) / 2, (min_y + max_y) / 2];
 71
 72    // subtract Voronoi pattern from the border polygon (disabled)
 73    difference() {
 74        //polygon(border);
 75        translate(center_poly) scale(scale_voro)
 76            random_voronoi(n = n, nuclei = false, L = L, thickness = thickness,
 77                  round = round, min = 0, max = L, seed = seed, center = true);
 78    }
 79
 80    // add the border edge if required
 81    if (edging) {
 82        difference() {
 83            polygon(border);
 84            offset(delta = -edging) polygon(border);
 85        }
 86    }
 87}
 88
 89module register(bottom_part=true){
 90applied_tolerance = bottom_part ? register_tolerance : -register_tolerance;
 91    translate([0,0,box_thickness/4])
 92tube(h=register_depth*2, od=box_diameter-wall_thickness+register_thickness+applied_tolerance, id=box_diameter-wall_thickness-register_thickness-applied_tolerance,$fn=
 93resolution);
 94for (i =  [0 : 1 : register_friction_bars]) {
 95angle_register_friction = 360*i/register_friction_bars;
 96computed_bar_radius = box_diameter/2-wall_thickness/2;
 97computed_bar_length = friction_bar_length+applied_tolerance/2;
 98computed_bar_radius_min_length = computed_bar_radius-computed_bar_length;
 99    translate([sin(angle_register_friction)*computed_bar_radius, cos(angle_register_friction)*computed_bar_radius, 0 ])
100    translate([0,0,box_thickness/4-register_depth]) rotate([0,0,-angle_register_friction])  cube([friction_bar_thickness+applied_tolerance/2,computed_bar_length,register_depth*2]);
101    translate([sin(angle_register_friction)*computed_bar_radius_min_length, cos(angle_register_friction)*computed_bar_radius_min_length, 0 ])
102    translate([0,0,box_thickness/4-register_depth]) rotate([0,0,-angle_register_friction])  cube([friction_bar_thickness+applied_tolerance/2,computed_bar_length,register_depth*2]);
103}
104}
105
106module box_half(bottom_part=true,voronoi_seed=1000){
107difference(){
108cyl(d=box_diameter, l=box_thickness/2, rounding1=box_rounding,$fn=
109resolution);
110if (textured_interior){
111translate([0,0,wall_thickness/2]) cyl(d=box_diameter-wall_thickness*2, l=box_thickness/2-wall_thickness, rounding1=box_rounding-wall_thickness, texture=interior_texture, tex_size=interior_texture_size,tex_scale=interior_texture_depth,$fn=
112resolution);
113} else {
114translate([0,0,wall_thickness/2]) cyl(d=box_diameter-wall_thickness*2, l=box_thickness/2-wall_thickness, rounding1=box_rounding-wall_thickness,$fn=
115resolution);
116}
117if (bottom_part){
118register(bottom_part);
119}
120potential_voronoi_texture(voronoi_seed);
121if (bottom_part){
122potential_texts();
123}
124if (!bottom_part){
125potential_binary();
126}
127}
128if (!bottom_part){
129register(bottom_part);
130}
131
132}
133
134external_texture_radius=box_diameter/2-box_rounding-wall_thickness;
135external_surface_offset =[0,0,-box_thickness/4];
136module potential_voronoi_texture(voronoi_seed=1000){
137if (voronoi_texture){
138border2 = [[box_diameter/2,box_diameter/2], [-box_diameter/2,box_diameter/2], [-box_diameter/2,-box_diameter/2], [box_diameter/2,-box_diameter/2]];
139translate(external_surface_offset)
140intersection(){
141linear_extrude(height = voronoi_texture_thickness) voronoi_polygon(border2,n=voronoi_count, thickness=voronoi_thickness, round=voronoi_rounding, edging=0, seed=voronoi_seed);
142    translate([0,0,wall_thickness/2])
143    cylinder(h=wall_thickness,r=external_texture_radius,center=true,$fn=
144resolution);
145    }
146    }
147}
148
149module revolve_text(radius, chars) {
150    PI = 3.14159;
151    circumference = 2 * PI * radius;
152    chars_len = len(chars);
153    font_size = circumference / chars_len;
154    step_angle = 360 / chars_len;
155    for(i = [0 : chars_len - 1]) {
156        rotate([0,180,i * step_angle]) 
157            translate([0, radius + font_size / 2, 0]) 
158                text(
159                    chars[i], 
160                    font = "Noto Sans Mono:style=bold", 
161                    size = font_size, 
162                    valign = "center", halign = "center"
163                );
164    }
165}
166
167module potential_text(radius,text_string){
168translate(external_surface_offset)
169linear_extrude(height = text_texture_thickness) revolve_text(radius, text_string);
170}
171
172module potential_texts(){
173if (text_texture){
174potential_text(external_texture_radius-6,"Ad astra per aspera. ");
175    potential_text(external_texture_radius-8*2,"OnTake. 2023. ");
176 }
177 }
178
179    module sector(radius, angles, fn = 24) {
180    r = radius / cos(180 / fn);
181    step = -360 / fn;
182
183    points = concat([[0, 0]],
184        [for(a = [angles[0] : step : angles[1] - 360]) 
185            [r * cos(a), r * sin(a)]
186        ],
187        [[r * cos(angles[1]), r * sin(angles[1])]]
188    );
189
190    difference() {
191        circle(radius, $fn = fn);
192        polygon(points);
193    }
194}
195
196module arc(radius, angles, width = 1) {
197    difference() {
198        sector(radius + width, angles,fn=resolution/2);
199        sector(radius, angles,fn=resolution/2);
200    }
201} 
202
203 
204module binary_arcs(radius,binary,width){
205    translate([(radius+width+binary_read_start_indicator_radius),0,0]) circle(r=binary_read_start_indicator_radius,$fn=resolution);
206    line_count=len(binary);
207    for(line_index = [0 : line_count - 1]) {
208    bin_count = len(binary[line_index]);
209    angle_inc = 360/bin_count;
210    for(i = [0 : bin_count - 1]) {
211        if (binary[line_index][i] == "1"){
212        arc(radius-line_index*width+width*binary_line_pad, [i*angle_inc,(i+(1-binary_angle_pad))*angle_inc], width*(1-binary_line_pad));
213        }
214    }
215}
216}
217
218module potential_binary(){
219if (binary_texture){
220translate(external_surface_offset)
221linear_extrude(height = binary_texture_thickness) binary_arcs(external_texture_radius-binary_width-binary_offset,binary_data,binary_width);
222 }
223 }
224
225
226
227box_half(true,bottom_voronoi_seed);
228
229other_half_offset = [hinge_length_adjusted-hinge_width,0,0];
230
231translate(other_half_offset) box_half(false,top_voronoi_seed);
232
233difference(){
234
235translate([-hinge_width/2,-hinge_width/2,-box_thickness/4]) cuboid([hinge_length_adjusted,hinge_width,hinge_thickness],rounding=hinge_rounding,
236    edges=["Z"],anchor=BOTTOM+FRONT+LEFT);
237    potential_voronoi_texture(bottom_voronoi_seed);
238    translate(other_half_offset) potential_voronoi_texture(top_voronoi_seed);
239    potential_texts();
240    translate(other_half_offset) potential_binary();
241    }